﻿#include "FieldScalarBarGenerator.h"

#include <vector>
#include <algorithm>
#include <vtkSmartPointer.h>
#include <vtkLookupTable.h>
#include <vtkScalarBarActor.h>
#include <vtkRenderer.h>
#include <vtkScalarsToColors.h>
#include <vtkPolyDataMapper.h>
#include <vtkCommand.h>
#include <vtkDataSetMapper.h>
#include <vtkRenderWindow.h>
#include <vtkCallbackCommand.h>
#include <FieldGraphGenerator.h>
#include <QCoreApplication>
#include <vtkTextProperty.h>
#include <vtkScalarBarWidget.h>
#include <vtkScalarBarRepresentation.h>
#include "ScalarBarSettingData.h"

namespace pst
{
    FieldScalarBarGenerator::FieldScalarBarGenerator(vtkRenderer* renderer, QObject* parent)
        : QObject(parent)
        , m_renderer(renderer)
        , m_scalarsScalarBarWidget(vtkSmartPointer<vtkScalarBarWidget>::New())
        , m_lookupTable(vtkSmartPointer<vtkLookupTable>::New())
        , m_scalarBarSettingData(new ScalarBarSettingData(this))
        , m_scalarBar(vtkSmartPointer<vtkScalarBarActor>::New())
    {
        qDebug() << "m_scalarBar pointer =  " << m_scalarBar;
        qDebug() << "m_scalarsScalarBarWidget pointer =  " << m_scalarsScalarBarWidget;
        // 1) 初始化 LookupTable
        m_lookupTable->SetNumberOfTableValues(256);
        m_lookupTable->SetNumberOfColors(150);
        m_lookupTable->SetHueRange(0.67, 0.0);
        m_lookupTable->Build();

        // 2) 初始化并添加 ScalarBarActor
        m_scalarBar->SetLookupTable(m_lookupTable);
        m_scalarBar->SetTitle("Shared Scalar Bar");
        m_scalarBar->SetNumberOfLabels(5);
        m_scalarBar->GetTitleTextProperty()->SetJustificationToLeft();
        m_scalarBar->SetBarRatio(0.2);
        m_scalarBar->SetUnconstrainedFontSize(true);
        //m_scalarBar->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
        //m_scalarBar->GetPositionCoordinate()->SetValue(0.05, 0.05);
        m_scalarBar->SetPosition(0.8, 0.1);
        m_scalarBar->SetPosition2(0.08, 0.7);
        m_scalarBar->GetTitleTextProperty()->SetColor(0, 0, 0);
        m_scalarBar->GetLabelTextProperty()->SetColor(0, 0, 0);
        m_scalarBar->GetLabelTextProperty()->SetFontSize(16);
        m_scalarBar->Modified();
        //m_scalarBar->SetWidth(0.2);
        //m_scalarBar->SetHeight(0.7);
        m_renderer->AddActor(m_scalarBar);

        m_scalarsScalarBarWidget->SetScalarBarActor(m_scalarBar);
        vtkScalarBarRepresentation* rep =
            vtkScalarBarRepresentation::SafeDownCast(m_scalarsScalarBarWidget->GetRepresentation());
        rep->SetPosition(0.8, 0.1);
        rep->SetPosition2(0.08, 0.7);
        m_scalarsScalarBarWidget->SetInteractor(renderer->GetRenderWindow()->GetInteractor());
        m_scalarsScalarBarWidget->On();


        // 3) 用 vtkCallbackCommand 构造桥接回调
        m_callbackCommand = vtkSmartPointer<vtkCallbackCommand>::New();
        m_callbackCommand->SetClientData(this);
        m_callbackCommand->SetCallback(&FieldScalarBarGenerator::staticRenderCallback);

        // 4) 在每次渲染前触发 updateRange()
        m_renderer->GetRenderWindow()
            ->AddObserver(vtkCommand::StartEvent, m_callbackCommand);

        QString currenEXEPath = QCoreApplication::applicationDirPath();
        auto micFont = currenEXEPath + "/Fonts/Alibaba-PuHuiTi-Regular.ttf";
        m_scalarBar->GetTitleTextProperty()->SetFontFamily(VTK_FONT_FILE);
        m_scalarBar->GetTitleTextProperty()->SetFontFile(micFont.toLocal8Bit());
    }

    void FieldScalarBarGenerator::addGraph(FieldGraphGenerator* graphGenerator)
    {
        m_graphGenerators.push_back(graphGenerator);
        auto mapper = graphGenerator->GetScalarsFieldActor()->GetMapper();
        mapper->ScalarVisibilityOn();
        mapper->SetLookupTable(m_lookupTable);
    }

    void FieldScalarBarGenerator::removeAGraph(FieldGraphGenerator* graphGenerator)
    {
        m_graphGenerators.removeOne(graphGenerator);
    }

    void FieldScalarBarGenerator::staticRenderCallback(vtkObject*, unsigned long, void* clientData, void*)
    {
        auto self = static_cast<FieldScalarBarGenerator*>(clientData);
        self->updateRange();
    }

    void FieldScalarBarGenerator::updateRange()
    {
        auto _isScalarBarAutoRange = getScalarBarSettingData()->getScalarBarAutoRange();
        auto _scalarBarMaxValue = getScalarBarSettingData()->getScalarBarMaxValue();
        auto _scalarBarMinValue = getScalarBarSettingData()->getScalarBarMinValue();
        auto _isShowTitle = getScalarBarSettingData()->getScalarBarIsShowTitle();
        auto _title = getScalarBarSettingData()->getScalarBarTitle();
        auto _titleColor = getScalarBarSettingData()->getScalarBarTitleColor();
        auto _fontSize = getScalarBarSettingData()->getScalarBarFontSize();
        auto _minValueOriginal = getScalarBarSettingData()->getScalarBarOriginalMinRange();
        auto _maxValueOriginal = getScalarBarSettingData()->getScalarBarOriginalMaxRange();
        auto _isLog = getScalarBarSettingData()->getScalarBarIsLog();
        auto _unit = getScalarBarSettingData()->getScalarBarUnit();

        //范围
        if (_isScalarBarAutoRange)
        {
            double gmin = std::numeric_limits<double>::infinity();
            double gmax = -std::numeric_limits<double>::infinity();

            for (auto& graphGenerator : m_graphGenerators)
            {
                std::array<double, 2> range = graphGenerator->GetActiveFieldOriginalRange();
                gmin = std::min(gmin, range[0]);
                gmax = std::max(gmax, range[1]);
            }
            m_lookupTable->SetRange(gmin, gmax);
        }
        else
        {
            m_lookupTable->SetRange(_scalarBarMinValue, _scalarBarMaxValue);
        }

        if (_isShowTitle)
        {
            QString _logStr = _isLog ? "dB" : "";
            QString postStr = "";
            if (!_logStr.isEmpty() || !_unit.isEmpty())
            {
                postStr = "[" + _logStr + _unit + "]";
            }
            QString title = _title + postStr;
            m_scalarBar->SetTitle(title.toStdString().c_str());
        }
        else
        {
            m_scalarBar->SetTitle("");
        }
        auto titleProperty = m_scalarBar->GetTitleTextProperty();
        titleProperty->SetFontSize(_fontSize);
        titleProperty->SetColor(_titleColor.redF(), _titleColor.greenF(), _titleColor.blueF());

        m_scalarBar->GetLabelTextProperty()->SetColor(_titleColor.redF(), _titleColor.greenF(), _titleColor.blueF());
        m_scalarBar->GetLabelTextProperty()->SetFontSize(_fontSize);

        //emit rangeChanged(gmin, gmax);
    }

}
